﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Main.PrimitivesCommunication;
using System.IO.Pipes;
using System.Threading;

namespace Main.Transport
{
    class CoucheTransport
    {
        
        public void EcrireVersReseau()
        {
            NamedPipeServerStream transportToReseauPipe = new NamedPipeServerStream(REGLES.PIPE_TRANSPORT_TO_RESEAU, PipeDirection.InOut, 10, PipeTransmissionMode.Message);
            NamedPipeClientStream transportToTransportPipe = new NamedPipeClientStream(REGLES.PIPE_TRANSPORT_TO_TRANSPORT);

            StreamWriter sw = new StreamWriter(transportToReseauPipe);
            StreamReader srtt = new StreamReader(transportToTransportPipe);

            using (StreamReader sr = new StreamReader(REGLES.S_LECTURE))
            {
                transportToReseauPipe.WaitForConnection();
                transportToTransportPipe.Connect();
                sw.AutoFlush = true;

                transportToTransportPipe.ReadMode = PipeTransmissionMode.Message;

                string line = String.Empty;
                //line = sr.ReadToEnd();
                while ((line = sr.ReadLine()) != null)
                {
                    string[] args = line.Split(';');

                    byte applicationId = Convert.ToByte(args[0]);
                    byte addresseDestination = Convert.ToByte(args[1]);
                    string data = args[2];

                    Connexion connexion = Connexion.GetConnexion(applicationId, addresseDestination);

                    if (connexion.Etat == EtatsConnexion.EnAttente)
                    {
                        Primitive connexionReq = Primitive.CreateNConnectReq(connexion.ApplicationId, connexion.AdresseDestination);

                        connexionReq.WriteJson(sw);
                    }

                    TraiterReponse(srtt);
                }

                TraiterReponse(srtt);
            }
        }

        public void TraiterReponse(StreamReader srtt)
        {
            string lineIdConnexion = String.Empty;

            while ((lineIdConnexion = srtt.ReadLine()) != null)
            {
                Connexion connection = Connexion.GetConnexion(Convert.ToByte(lineIdConnexion));

                if (connection.Etat == EtatsConnexion.ConnexionEtablie)
                {
                    Primitive primitiveReponse;
                    foreach (string data in connection.Data)
                    {
                        primitiveReponse = Primitive.CreateNDataReq(data);
                        using (StreamWriter swtt = new StreamWriter(REGLES.S_ECRITURE))
                        {
                            swtt.WriteLine(primitiveReponse.ToString());
                        }
                    }
                }
            }
        }

        public void LireDeReseau()
        {

            NamedPipeClientStream reseauToTransportPipe = new NamedPipeClientStream(REGLES.PIPE_RESEAU_TO_TRANSPORT);
            NamedPipeServerStream transportToTransportPipe = new NamedPipeServerStream(REGLES.PIPE_TRANSPORT_TO_TRANSPORT,PipeDirection.InOut,10,PipeTransmissionMode.Message);
           
            StreamReader srReseauToTransport = new StreamReader(reseauToTransportPipe);
            StreamWriter swTransportToTransport = new StreamWriter(transportToTransportPipe);

            reseauToTransportPipe.Connect();
            transportToTransportPipe.WaitForConnection();

            transportToTransportPipe.ReadMode = PipeTransmissionMode.Message;

            String line, envoiToEcrire = null;
            Primitive primitiveReceived = null;
            
            while ((line = srReseauToTransport.ReadLine()) != null)
            {
                Console.WriteLine(line);

                primitiveReceived = Primitive.ReadJson(line);
                Connexion connection = Connexion.GetConnexion(primitiveReceived.AdresseDestination, primitiveReceived.AdresseSource);

                switch (primitiveReceived.Primitives)
                { 
                    case Primitives.NConnectConfirmation:
                        connection.Etat = EtatsConnexion.ConnexionEtablie;
                        envoiToEcrire = connection.IdConnexionLogique.ToString();
                        break;

                    case Primitives.NDisconnectIndication:
                        connection.Destroy();
                        break;
                }

                swTransportToTransport.WriteLine(envoiToEcrire);

                if (primitiveReceived.Primitives == Primitives.NConnectConfirmation  ||
                    primitiveReceived.Primitives == Primitives.NConnectIndication    ||
                    primitiveReceived.Primitives == Primitives.NDisconnectIndication ||
                    primitiveReceived.Primitives == Primitives.NDataIndication)
                {
                    using (StreamWriter sw = new StreamWriter(REGLES.S_ECRITURE))
                    {
                        sw.WriteLine(primitiveReceived.ToString());
                    }
                }
            }
        }
    }
}
